﻿using Abp.Dependency;
using GN.Pay.Core.Repositories;
using GN.Pay.TradeChannel;
using GN.Pay.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace GN.Pay.Core.Startup
{
    /// <summary>
    /// 交易通道安装
    /// </summary>
    public class TradeChannelInstaller
    {
        private static TradeChannelInstaller instance = new TradeChannelInstaller();

        /// <summary>
        /// 获取实例
        /// </summary>
        public static TradeChannelInstaller Instance
        {
            get
            {
                return TradeChannelInstaller.instance;
            }
        }

        private readonly Dictionary<string, Type> channel_Types;

        private TradeChannelInstaller()
        {
            this.channel_Types = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iocManager"></param>
        /// <param name="assembly"></param>
        public void Register(ITradeChannelRepository tradeChannelRepository, Assembly assembly)
        {
            lock (this)
            {
                var types = TypeUtils.GetDefaultConstructorAssignableTypes<ITradeChannel>(assembly, null, true);
                foreach (var type in types)
                {
                    ITradeChannel channel = (ITradeChannel)Activator.CreateInstance(type);
                    string id = null;
                    try
                    {
                        id = channel.ChannelId;
                        AddOrUpdateChannel(tradeChannelRepository, channel);
                    }
                    catch (Exception)
                    {
                    }
                    if (id != null)
                    {
                        channel_Types[id] = type;
                    }
                }
            }
        }

        private void AddOrUpdateChannel(ITradeChannelRepository tradeChannelRepository, ITradeChannel channel)
        {
            var tc = tradeChannelRepository.Get(channel.ChannelId);
            if (tc == null)
            {
                tc = new Entities.TradeChannel()
                {
                    Id = channel.ChannelId,
                    ChannelName = channel.ChannelName,
                    ChannelProvider = channel.ChannelProvider,
                    ChannelType = (int)channel.ChannelType,
                    State = 1
                };
                tradeChannelRepository.Insert(tc);
            }
            else
            {
                int count = 0;
                if(tc.ChannelName!= channel.ChannelName)
                {
                    tc.ChannelName = channel.ChannelName;
                    count++;
                }
                if (tc.ChannelProvider != channel.ChannelProvider)
                {
                    tc.ChannelProvider = channel.ChannelProvider;
                    count++;
                }
                var channelType = (int)channel.ChannelType;
                if (tc.ChannelType != channelType)
                {
                    tc.ChannelType = channelType;
                    count++;
                }
                if (count > 0)
                {
                    tradeChannelRepository.Update(tc);
                }
            }
        }

        /// <summary>
        /// 获取所有交易通道类型
        /// </summary>
        /// <returns></returns>
        public List<Type> GetTradeChannelTypes()
        {
            lock (this)
            {
                return channel_Types.Values.ToList();
            }
        }

        /// <summary>
        /// 获取是否注册类型
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public bool IsRegisterChannelType(Type type)
        {
            lock (this)
            {
                return channel_Types.Values.Count(t => t.Equals(type)) > 0;
            }
        }

        /// <summary>
        /// 获取是否注册类型
        /// </summary>
        /// <param name="channelId">通道id</param>
        /// <returns></returns>
        public bool IsRegisterChannel(string channelId)
        {
            lock (this)
            {
                return channel_Types.ContainsKey(channelId);
            }
        }

        /// <summary>
        /// 创建通道
        /// </summary>
        /// <param name="channelId">通道id</param>
        /// <returns></returns>
        public ITradeChannel CreateTradeChannel(string channelId)
        {
            var type = this.GetTradeChannelType(channelId);
            if (type == null)
            {
                throw new ArgumentNullException(nameof(channelId), channelId + " 未注册");
            }
            return (ITradeChannel)Activator.CreateInstance(type);
        }

        /// <summary>
        /// 获取通道类型
        /// </summary>
        /// <param name="channelId">通道id</param>
        /// <returns></returns>
        public Type GetTradeChannelType(string channelId)
        {
            if (channelId == null)
            {
                throw new ArgumentNullException(nameof(channelId));
            }
            lock (this)
            {
                Type type;
                if (channel_Types.TryGetValue(channelId, out type))
                {
                    return type;
                }
                return null;
            }
        }

    }
}
